package com.anry.weatherforecast.service;

import com.anry.weatherforecast.utils.FixedAliYunSignatureUtil;
import okhttp3.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 阿里云快递物流查询服务实现类
 */
@Service
public class ExpressTrackingService {
    
    // API配置
    private static final String API_PATH = "/lundear/expressTracking";
    private static final String API_URL = "https://qrykd.market.alicloudapi.com/lundear/expressTracking";
    
    // 应用凭证（设置为常量）
    @Value("${anry.appkey}")
    private String APP_KEY ;
    @Value("${anry.appsecret}")
    private  String APP_SECRET;

    private final OkHttpClient client;
    private final ObjectMapper objectMapper;
    
    public ExpressTrackingService() {
        this.client = createUnsafeOkHttpClient();
        this.objectMapper = new ObjectMapper();
    }

    /**
     * 创建跳过SSL验证的HTTP客户端
     */
    private OkHttpClient createUnsafeOkHttpClient() {
        try {
            javax.net.ssl.X509TrustManager trustManager = new javax.net.ssl.X509TrustManager() {
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                }

                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                }

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return new java.security.cert.X509Certificate[]{};
                }
            };

            javax.net.ssl.SSLContext sslContext = javax.net.ssl.SSLContext.getInstance("SSL");
            sslContext.init(null, new javax.net.ssl.TrustManager[]{trustManager}, new java.security.SecureRandom());
            
            return new OkHttpClient.Builder()
                    .sslSocketFactory(sslContext.getSocketFactory(), trustManager)
                    .hostnameVerifier((hostname, session) -> true)
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .readTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .build();
                    
        } catch (Exception e) {
            throw new RuntimeException("创建HTTP客户端失败", e);
        }
    }
    
    /**
     * 查询快递物流信息（仅提供快递单号）
     * 
     * @param number 快递单号（必需）
     * @return 响应结果
     */
    public String queryExpressTracking(String number) throws Exception {
        return queryExpressTracking(number, null, null);
    }
    
    /**
     * 查询快递物流信息（提供快递单号和快递公司代码）
     * 
     * @param number 快递单号（必需）
     * @param com 快递公司代码（可选）
     * @return 响应结果
     */
    public String queryExpressTracking(String number, String com) throws Exception {
        return queryExpressTracking(number, com, null);
    }
    
    /**
     * 查询快递物流信息（完整参数）
     * 
     * @param number 快递单号（必需）
     * @param com 快递公司代码（可选）
     * @param mobile 收件人/寄件人手机号后4位（可选，顺丰和丰网需要）
     * @return 响应结果
     */
    public String queryExpressTracking(String number, String com, String mobile) throws Exception {
        System.out.println("=== 开始查询快递物流信息 ===");
        
        // 准备查询参数
        Map<String, String> queryParams = new HashMap<>();
        queryParams.put("number", number);
        
        if (com != null && !com.isEmpty()) {
            queryParams.put("com", com);
        }
        
        if (mobile != null && !mobile.isEmpty()) {
            queryParams.put("mobile", mobile);
        }
        
        // 发送查询请求
        return sendQueryRequest(queryParams);
    }
    
    /**
     * 发送查询请求的核心方法
     * 
     * @param queryParams 查询参数
     * @return 响应结果
     */
    private String sendQueryRequest(Map<String, String> queryParams) throws Exception {
        System.out.println("开始构造快递查询请求");
        
        // 准备签名参数
        String timestamp = FixedAliYunSignatureUtil.getCurrentTimestamp();
        String nonce = FixedAliYunSignatureUtil.generateNonce();
        
        // 参与签名的Headers
        Map<String, String> signHeaders = new HashMap<>();
        signHeaders.put("X-Ca-Key", APP_KEY);
        signHeaders.put("X-Ca-Timestamp", timestamp);
        signHeaders.put("X-Ca-Nonce", nonce);
        
        String signatureHeaders = FixedAliYunSignatureUtil.getSignatureHeaders(signHeaders);
        System.out.println("参与签名的Headers: " + signatureHeaders);

        // 计算签名
        String signature = FixedAliYunSignatureUtil.calculateSignature(
                APP_SECRET,          // secret
                "GET",               // method
                "application/json",  // accept
                "",                  // contentMD5
                "",                  // contentType
                "",                  // date
                signHeaders,         // headers
                API_PATH,            // path
                queryParams,         // queryParams
                null                 // formParams
        );

        // 设置签名到请求头
        signHeaders.put("X-Ca-Signature", signature);
        signHeaders.put("X-Ca-Signature-Headers", signatureHeaders);
        signHeaders.put("Accept", "application/json");
        
        // 构造查询字符串
        String queryString = buildQueryString(queryParams);
        String fullUrl = API_URL + (queryString.isEmpty() ? "" : "?" + queryString);
        System.out.println("完整请求URL: " + fullUrl);

        // 构造请求头
        Headers headers = new Headers.Builder()
                .add("Accept", "application/json")
                .add("X-Ca-Key", APP_KEY)
                .add("X-Ca-Signature", signature)
                .add("X-Ca-Timestamp", timestamp)
                .add("X-Ca-Nonce", nonce)
                .add("X-Ca-Signature-Headers", signatureHeaders)
                .build();

        // 构造空的请求体
        RequestBody body = RequestBody.create("", MediaType.parse("application/json"));

        // 发送请求
        Request request = new Request.Builder()
                .url(fullUrl)
                .headers(headers)
                .get() // 使用GET方法
                .build();
        
        System.out.println("发送GET请求到: " + fullUrl);
        
        try (Response response = client.newCall(request).execute()) {
            System.out.println("响应状态码: " + response.code());
            System.out.println("响应消息: " + response.message());
            
            // 打印响应头
            System.out.println("响应头:");
            for (String name : response.headers().names()) {
                System.out.println("  " + name + ": " + response.headers().get(name));
            }
            
            if (!response.isSuccessful()) {
                String errorBody = response.body() != null ? response.body().string() : "无响应体";
                System.out.println("错误响应体: " + errorBody);
                
                // 检查是否有详细的错误信息
                String errorMessage = response.header("X-Ca-Error-Message");
                if (errorMessage != null) {
                    System.out.println("详细错误信息: " + errorMessage);
                }
                
                throw new RuntimeException("API请求失败: " + response.code() + " - " + response.message());
            }
            
            ResponseBody responseBody = response.body();
            if (responseBody != null) {
                String result = responseBody.string();
                System.out.println("请求成功！响应长度: " + result.length());
                System.out.println("响应内容: " + result);
                return result;
            } else {
                throw new RuntimeException("响应体为空");
            }
        }
    }
    
    /**
     * 构建查询字符串
     * 
     * @param params 参数映射
     * @return 查询字符串
     */
    private String buildQueryString(Map<String, String> params) {
        if (params == null || params.isEmpty()) {
            return "";
        }
        
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (!first) {
                sb.append("&");
            }
            
            sb.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8));
            if (entry.getValue() != null) {
                sb.append("=").append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
            }
            
            first = false;
        }
        
        return sb.toString();
    }
}
